package stateDiagram;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jhotdraw.draw.Drawing;
import org.jhotdraw.draw.Figure;
import stateDiagram.EntityObjects.StateEntity;
import stateDiagram.EntityObjects.SuperStateEntity;
import stateDiagram.EntityObjects.TransitionEntity;
import stateDiagram.figures.StateFigure;
import stateDiagram.figures.StartStateFigure;
import stateDiagram.figures.EndStateFigure;

public class SimulationEngine {
	
	
	/*
	 * Pseudo code of how this will go down:
//Parse
Determine type of file first
If XML
    Use XMLParser to get simulation parsed
If not XML
    Use FileLoader to get simulation parsed

//Simulate Diagram
While EventFile.hasNextLine
    GetNextLine
    For each transition in State
        if transition.event = nextline
            state = transition.endstate
            actions = actions + transitions.action
            break for loop
        if no more transitions
            actions = actions + error
    If current state = end state
        actions = actions + error(remaining events)

//Output Events
Filestream out for the new eventfile
out = out + actions
	 */

	public String simulate(Drawing drawing, URI filePathIn){
		String  r = new String();
		try {
			//Parse instructions
			FileReader fr = new FileReader(new File(filePathIn));
			BufferedReader simInstructions = new BufferedReader(fr);
			
			
			
			//Simulate
			//Prepare states for iterating
			List<Figure> allFigures = drawing.getChildren();
			List<Figure> states = new ArrayList<Figure>();
			StateEntity currentState = null;
			
			Iterator<Figure> it = allFigures.iterator();
			while (it.hasNext()){
				Figure f = it.next();
				if (f != null){
					if (f instanceof StateFigure
							|| f instanceof StartStateFigure
							|| f instanceof EndStateFigure)
						states.add(f);
					if (f instanceof StartStateFigure)
						currentState = ((StartStateFigure) f).getStateEntity();
				}
			}
			
			//Find start state
			
			boolean startNotFound = (currentState == null);
			
			if (startNotFound){
				r.concat("No start state found, unable to simulate.");
			}
			else {
				//Go through each simulation instruction
				String instr;
				int linenumber = 1;
				StateEntity nextState = null;
				TransitionEntity nextTransition = null;
				SuperStateEntity currentSuperState = null;
				String actionTaken = "";
				
				
				while ((instr = simInstructions.readLine()) != null){
					instr = instr.trim();// get rid of endline and extra spaces or they wont match- james
					//System.out.println(instr + "is the event we are looking for");//debug
					//First see if we leave the superstate if we're under one.
					
					nextState = null;
					
					if (currentSuperState != null){
						ArrayList<TransitionEntity> possibleOuts = currentSuperState.getOutgoingTransitions();
						Iterator<TransitionEntity> superit = possibleOuts.iterator();
						
						while (superit.hasNext() && nextState == null){
							nextTransition = superit.next();
							if (nextTransition.getName().equals(instr)
									&& !nextTransition.isInternalTransition()){
								nextState = nextTransition.getNextState();
								actionTaken = nextTransition.getAction();
							}
						}
					}
					
					//See if our current state can do anything with the next event
					
					
					ArrayList<TransitionEntity> possibleTrans = currentState.getOutgoingTransitions();
					Iterator<TransitionEntity> ptit = possibleTrans.iterator();
					//for(TransitionEntity e: possibleTrans){
					//System.out.println(e.toXML());
					//}///debug

					while (ptit.hasNext() && nextState == null){
						//See if ptit.next's event is equal to instr
						//If yes, nextState = state that ptit.next connects to
						nextTransition = ptit.next();
						
						if (nextTransition.getName().equals(instr)){
							
							nextState = nextTransition.getNextState();
							actionTaken = nextTransition.getAction();
							//System.out.println(actionTaken);//debug
						}
					}
					
					if (nextState == null){
						r = r + ("Line " + linenumber + ": Event '" + instr + "' not applicable to current state, staying at " + currentState.getName() + ". \n" );
					}
					//else if nexttransition has action
						//simoutput.write (line #: action)
					else{
						//System.out.println(" do we get here?");//debug
						if(currentState.getFigure() != null){
							r = r + (currentState.getExitAction() + "(exit)\n");
						}
						r = r + ("Line " + linenumber + ": " + actionTaken + " \n");
						if (nextState.getFigure() != null){
							r = r + (nextState.getEntryAction() + "(entry)\n");
						}
						
						currentState = nextState;
						
						if (currentState instanceof SuperStateEntity)
							currentSuperState = (SuperStateEntity) currentState;
						
						//System.out.println(currentState.toXML());//debug
		
					}
					
					linenumber++;
				}
				
				r = r + ("Simulation complete.\n");
				if (currentState.getName().equals("end")){
					r = r + ("Simulation reached the end of the diagram.");
				} else {
					r = r + ("Simulation ended in state " + currentState.getName() + ".");
				}
				simInstructions.close();
				fr.close();
				
							
			}
			//System.out.println(r);
			//resultsOut = r;
		}
		catch (IOException e){
			//Some type of error check?
			e.printStackTrace();
		}
		return r;
	}
	
	public void simulate(Drawing drawing, URI filePathIn, URI filePathOut){
		String s = new String();
		simulate(drawing, filePathIn);
		try {
			FileWriter fw = new FileWriter(filePathOut.getPath());
			BufferedWriter bw = new BufferedWriter(fw);
			bw.write(s);
			bw.close();
			fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
